// $Id: persister.c,v 1.1.1.1 2012/02/17 03:45:26 hzheng Exp $

#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#include "log.h"
#include "repo.h"
#include "obj_xml.h"

#include "persister.h"

static int evcpe_persister_persist(struct evcpe_persister *persist);

struct evcpe_persister *evcpe_persister_new(struct event_base *evbase)
{
	struct evcpe_persister *persist;

	evcpe_debug(__func__, "constructing evcpe_persister");

	if (!(persist = calloc(1, sizeof(struct evcpe_persister)))) {
		evcpe_error(__func__, "failed to calloc evcpe_persister");
		return NULL;
	}
	if (!(persist->buffer = evbuffer_new())) {
		evcpe_error(__func__, "failed to create evbuffer");
		free(persist);
		return NULL;
	}
	persist->evbase = evbase;
//	persist->timer_tv.tv_sec = 5;
	return persist;
}

void evcpe_persister_free(struct evcpe_persister *persist)
{
	if (!persist) return;

	evcpe_debug(__func__, "destructing evcpe_persister");

	if (event_initialized(&persist->timer_ev) && evtimer_pending(
			&persist->timer_ev, NULL)) {
		event_del(&persist->timer_ev);
	}
	if (evtimer_initialized(&persist->timer_ev) && evtimer_pending(
			&persist->timer_ev, NULL)) {
		event_del(&persist->timer_ev);
	    if (evcpe_persister_persist(persist))
		    evcpe_error(__func__, "failed to write buffer");
	}
	free(persist);
}

int evcpe_persister_persist(struct evcpe_persister *persist)
{
	int rc, fd;
	FILE *fp;

	evcpe_debug(__func__, "persisting repository");

	if (!(fp = fopen(persist->filename, "w+"))) {
		evcpe_error(__func__, "failed to open file to write: %s", persist->filename);
		rc = errno ? errno : -1;
		goto finally;
	}
	fd = fileno(fp);
	evbuffer_drain(persist->buffer, EVBUFFER_LENGTH(persist->buffer));
	if ((rc = evcpe_obj_to_xml(persist->repo->root, persist->buffer))) {
		evcpe_error(__func__, "failed to marshal root object");
		goto finally;
	}
	evcpe_debug(__func__, "%d %s", (int)(EVBUFFER_LENGTH(persist->buffer)),
			EVBUFFER_DATA(persist->buffer));
    while (EVBUFFER_LENGTH(persist->buffer)) {
    	if (evbuffer_write(persist->buffer, fd) < 0) {
			evcpe_error(__func__, "failed to write buffer");
			rc = errno ? errno : -1;
			goto finally;
    	}
    }
	rc = 0;

finally:
	if (fp) fclose(fp);
	return rc;
}

